import { acceptHMRUpdate, defineStore, storeToRefs } from 'pinia'
import { store } from '../index'
import { CACHE_KEY, useCache } from '@/hooks/web/useCache'
import { decodeAES, encodeAES } from '@/utils/aesRsa'
import { getAccessToken, removeToken } from '@/utils/auth'
import { useAppStoreWithOut } from '@/store/modules/app'
import { useTagCacheStoreWithOut } from '@/store/modules/tag'
import { useKeepAliveStoreWithOut } from '@/store/modules/keepAlive'
import type { UserProfileUpdateReqType } from '@/api/system/user/profile'
import type { UserType } from '@/api/auth/types'
import { AuthApi } from '@/api/auth'
import router from '@/router'
import * as routerHelper from '@/utils/routerHelper'
import { cloneDeep } from 'lodash-es'
import { localRouter } from '@/router/local'

export const useUserStore = defineStore('user', () => {
  const { wsLocal } = useCache()

  const tagCacheStore = useTagCacheStoreWithOut()
  const appStore = useAppStoreWithOut()
  const { systemConfig } = storeToRefs(appStore)
  const keepAliveStore = useKeepAliveStoreWithOut()

  const user = ref<UserType>(null) // 用户信息
  const permitList = ref<string[]>([]) // 用户权限操作
  const menus: any = ref<AppRouteRecordRaw[]>([]) // 用户权限菜单 包含不在侧边栏显示的数据
  const menuList: any = ref<AppRouteRecordRaw[]>([]) // 用户权限菜单 去除不在侧边栏显示的数据
  const routerList = ref([]) // 用户权限路由
  const hasChildrenMenu = ref(true) // 当前菜单的根级菜单是否有子菜单

  // 设置用户信息
  const setUserInfoAction = async () => {
    if (!getAccessToken()) {
      removeUserInfoCache()
      return null
    }
    let userInfo = wsLocal.getItem(CACHE_KEY.USER_INFO)
    if (!userInfo) {
      userInfo = await AuthApi.info()
    } else {
      userInfo = decodeAES(wsLocal.getItem(CACHE_KEY.USER_INFO))
    }
    user.value = userInfo.user
    permitList.value = userInfo.permit

    // -------------------------  菜单相关处理

    // 后端获取菜单数据
    // 将动态路由字段转化为前端字段并处理成规范路由格式数据，根据第二个参数对数据进行区分处理
    const dynamicMenus = routerHelper.dataFieldInvert(cloneDeep(userInfo.menus), true)

    // 本地管理菜单数据
    // 将本地管理的动态路由字段转化为前端字段并处理成规范路由格式数据，根据第二个参数对数据进行区分处理
    const localAllMenus = routerHelper.dataFieldInvert(cloneDeep(localRouter), true)
    // 过滤掉本地动态路由中的无权限路由数据，只保留 permitList.value 中包含的路由数据，及无需权限验证的路由数据
    const localPermitMenus = routerHelper.filterLocalPermitData(permitList.value, cloneDeep(localAllMenus))
    // 获取合并后的权限菜单数据
    const permitMenus = routerHelper.getPermitMenus(cloneDeep(dynamicMenus), cloneDeep(localPermitMenus))
    // 菜单原始数据格式化
    menus.value = routerHelper.permitMenuFormat(cloneDeep(permitMenus))
    // 获取可在侧边栏显示的菜单数据
    const sidebarMenuList = routerHelper.filterVisibleStatusMenu(cloneDeep(permitMenus))
    // 侧边显示的菜单数据格式化
    menuList.value = routerHelper.sidebarMenuFormat(sidebarMenuList)

    // -------------------------- 路由相关处理

    // 后端获取菜单数据
    // 将动态路由字段转化为前端字段并处理成规范路由格式数据，根据第二个参数对数据进行区分处理
    const dynamicRoutes = routerHelper.dataFieldInvert(cloneDeep(userInfo.menus), false)
    // 过滤掉动态路由中的目录类型数据，该类数据不需要实例化
    const dynamicPermitRoutes = routerHelper.filterMenuTypeRoute(cloneDeep(dynamicRoutes))

    // 本地管理菜单数据
    // 将本地管理的动态路由字段转化为前端字段并处理成规范路由格式数据，根据第二个参数对数据进行区分处理
    const localAllRoutes = routerHelper.dataFieldInvert(cloneDeep(localRouter), false)
    // 过滤掉本地动态路由中的目录类型数据，该类数据不需要实例化
    const localRoutes = routerHelper.filterMenuTypeRoute(cloneDeep(localAllRoutes))
    // 过滤掉本地动态路由中的无权限路由数据，只保留 permitList.value 中包含的路由数据，及无需权限验证的路由数据
    const localPermitRoutes = routerHelper.filterLocalPermitData(permitList.value, cloneDeep(localRoutes))
    // 获取最终需要实例化的路由数据
    routerList.value = routerHelper.getPermitRoutes(cloneDeep(dynamicPermitRoutes), cloneDeep(localPermitRoutes))
    wsLocal.setItem(CACHE_KEY.USER_INFO, encodeAES(userInfo))
  }

  // 登出
  const signOut = async () => {
    await AuthApi.signOut()
    removeUserInfoCache()
    removeToken()
    tagCacheStore.removeAllTagCache()
    tagCacheStore.removeFixedTagCache()
    keepAliveStore.removeAllKeepAlive()
    systemConfig.value.isLogin = false
    appStore.setSystemConfigCache()
    routerHelper.resetRouter()
    nextTick(() => {
      if (!router.currentRoute.value.fullPath.includes('/Login?redirect=')) {
        router.push(`/Login?redirect=${router.currentRoute.value.fullPath}`)
        window.location.href = window.location.href
      }
    })
  }

  const removeUserInfoCache = () => {
    wsLocal.removeItem(CACHE_KEY.USER_INFO)
    resetState()
  }

  const resetState = () => {
    user.value = null
    permitList.value = []
    menuList.value = []
    routerList.value = []
  }

  // 更新头像
  const setUserAvatarAction = (avatar: string) => {
    const userInfo = decodeAES(wsLocal.getItem(CACHE_KEY.USER_INFO))
    userInfo.user.avatar = avatar
    if (user.value) {
      user.value.avatar = avatar
    } else {
      user.value = userInfo.user
    }
    wsLocal.setItem(CACHE_KEY.USER_INFO, encodeAES(userInfo))
  }

  // 更新基本信息
  const setUserBasicInfoAction = (basicInfo: UserProfileUpdateReqType) => {
    const userInfo = decodeAES(wsLocal.getItem(CACHE_KEY.USER_INFO))
    userInfo.user.nickname = basicInfo.nickname
    userInfo.user.email = basicInfo.email
    userInfo.user.sex = basicInfo.sex
    userInfo.user.mobile = basicInfo.mobile
    if (user.value) {
      user.value.nickname = basicInfo.nickname
      user.value.email = basicInfo.email
      user.value.sex = basicInfo.sex
      user.value.mobile = basicInfo.mobile
    } else {
      user.value = userInfo.user
    }
    wsLocal.setItem(CACHE_KEY.USER_INFO, encodeAES(userInfo))
  }

  // 判断根级菜单是否有子菜单
  const watchMenuChange = menu => {
    hasChildrenMenu.value = routerHelper.hasChildrenMenuFn(menuList.value, menu)
  }

  return {
    user,
    permitList,
    menus,
    menuList,
    routerList,
    hasChildrenMenu,
    watchMenuChange,
    setUserInfoAction,
    removeUserInfoCache,
    signOut,
    setUserAvatarAction,
    setUserBasicInfoAction
  }
})

if (import.meta.hot) {
  import.meta.hot.accept(acceptHMRUpdate(useUserStore, import.meta.hot))
}

export const useUserStoreWithOut = () => {
  return useUserStore(store)
}
